Introduction
We covered one-way ANOVA, randomized block design, and multifactorial
design. As you may have already figured, we started with simple
experimental designs, and gradually move towards more complex
experimental designs.
This time, we will cover experimental designs involving repeated
measures. We will cover
- Why is repeated measure a problem for ANOVA?
- What is a random effect?
- How to set up a mixed effect model?
- How to analyze a mixed effect model?
Load packages
library(lme4)
library(lmerTest) #two new packages
library(emmeans)
library(multcomp)
library(multcompView)
library(ggplot2)
library(tidyr)
library(dplyr)
library(readr)
library(readxl)
library(RColorBrewer)
library(viridis)
Why is repeated measure
a problem for ANOVA
Repeated measures refer to the fact that in some experiments, the
same entity is measured multiple times. How could that be?
Let’s imagine an experiment like this:
Say I am tracking the heights of some rice plants over time. Every
week, I go to measure the height of those plants.
And THAT is a kind of repeated measure. The same plants are
measured multiple times throughout the experiment. Whenever the same
entity is measured multiple times (either across time or space), it is a
repeated measures experiment.
Let’s go over another example. Say I am interested in the number of
seeds per plant across two genotypes of rice. There are three pots per
genotype, and three plants per pot. (All three plants in a pot are the
same genotype.) Then I count the number of seeds in each plant.
And THAT is a repeated measure. The pots are being repeatedly
measured for the plants in them. And the pots cannot be used as a
blocking factor, because there is only one genotype per pot.
But why is that a problem? Remember, the assumption of ANOVA is that
each observation is independent of the other. And repeated measures is a
violation of that assumption. When multiple measurements of the same
entity were taken, those measurements will NOT be independent of each
other, because they are all affected by the same entity.
Repeated measures always reduce the number of independent
observations you have, and one must correct for repeated measures.
Working with repeated
measures - using random effects
To correct for repeated measures, we need to declare the entities
that are repeatedly measured as “random effects”.
This is a very abstract concept. So the best way to explain is to use
an example.
We are comparing the height of two rice genotypes, WT and mutant,
through time. Every week we measure the heights of those plants. (Data
from Sundaresan Lab, Department Of Plant Biology, UC Davis)
rice_growth <- read_csv("https://raw.githubusercontent.com/johnshorter/TeachingData/refs/heads/main/rice_growth_data.csv")
head(rice_growth)
In this experiment, each pot was randomly assigned a genotype, either
WT or mutant. The mutant is called “48/48”. There was one plant per pot.
The total of 48 pots were randomly placed into 6 flats, and 8 pots per
flat. So the flat was a blocking factor. We measure the height every
week, starting from week 3 to week 9, (but not week 8), so total of 6
time points.
Before we talk about random effects, we need to talk about fixed
effects. Simply put, the fixed effects are your treatments. In this
example, We have two fixed effects: genotype and age.
Let’s look at all the factors in this experiment
| time |
treat |
6 |
| genot |
treat |
2 |
| flat |
block |
6 |
| pot |
EU |
48 |
Because there are two independent variables (time and genotype) and
one blocking factor, this experiment will be called a randomized block
multifactorial design.
Note In this example, plant or pot is the experimental unit
for genotype, because the treatment of genotype was applied to each pot,
and there is only one plant in each pot. Note Pot is also the
entity that has been repeatedly measured through weeks.
You might ask, then where is the observational unit? The OU is actual
the plant at each week, or the plant:week combination.
Coming back to random effects. What is a random effect?
- A random effect CANNOT be a treatment (because they are
fixed effects);
- An EU that is not an OU must be declared as a random effect;
- An entity that is repeatedly measured must be declared as a random
effect;
- Blocking factors can be declared as random effects, but they don’t
have to.
So in this example, what needs to be declared as a random effect? The
pot needs to be declared as a random effect, since it is both the EU for
genotype and the entity of repeated measures.
Setting up a mixed
effect model
A mixed effect model refers to a model that contains both fixed
effects and random effects. A mixed effect model is appropriate for this
experiment, because we have two fixed effects (time and genotype) and
one random effect (pot). #### note, pot is the covariate within which we
have repeated measures
How do I set up the model? To set up the mixed effect model, we will
need a new function. Instead of lm(), we will use
lmer(). This will be the command for mixed effect linear
model.
To specify a random effect, we’ll use the
(1|random_effect) syntax. In this example, it will be
(1|pot)
In the model, you will put in your fixed effect and interactions
first, then you put in blocking factors, then you put in random effects.
So the model will be
lmer(height ~ time + genotype + time:genotype + flat + (1|pot))
You can also do time*genotype + flat + (1|pot). That gives
you the same thing.
Do not include the interactions with blocking factors (flat). The
blocking factor only exists to control for unintended variations. And we
are not interested in the flat:time or flat:genotype effects.
You might ask can I do
height ~ genotype * time + flat + (1|plant)? In an
experiment like this,
you should put the non-manipulative factor (time) first,
then you put the manipulative factor (genotype) second.
The reason is that in a mixed effect model, the first factor in the
model will account for variation first; then the rest of the variation
will be passed on to the second factor in the model, and so on.
By common sense, we know plants grow taller over time. So we expect
that time explains more variation than genotype. So we will put time
first in the model.
You can also declare the flat as a random effect by using
(1|flat). Either way is correct, but setting the flat as a
random effect is more conservative, meaning you’ll need a larger
difference in mean to detect a significant difference
Last thing: before you set up the model, is there any numeric
variables that you need to change to factors?
rice_growth <- rice_growth %>%
mutate(age.f = factor(age_weeks)) %>%
mutate(flat.f = factor(flat))
model_rice <- lmer(Height_mm ~ age.f * genotype + (1|flat.f) + (1|pot), data = rice_growth)
Data visualization
Before we do any analysis, let’s plot the data and look at it first.
Plot age.f on x axis, and Height_mm on y axis. Color by genotype.
Make the best plot you can here:
wisteria <- c("grey65", "burlywood3", "khaki2", "plum1", "lightcyan2", "cornflowerblue", "slateblue3")
rice_growth %>%
ggplot(aes(x = age_weeks, y = Height_mm)) +
stat_summary(geom = "line",
fun = mean,
aes(group = genotype, color = genotype),
size = 1.2) +
stat_summary(geom = "ribbon",
fun.data = mean_se,
aes(group = genotype,
fill = genotype),
alpha = 0.5) +
geom_point(aes(fill = genotype),
position = position_jitter(0.1, seed = 666),
alpha = 0.8,
size = 3,
shape = 21,
color = "black") +
scale_fill_manual(values = wisteria[c(1, 7)]) +
scale_color_manual(values = wisteria[c(1, 7)]) +
scale_x_continuous(breaks = c(3, 4, 5, 6, 7, 9)) +
labs(x = "Age (weeks)",
y = "Height mm",
fill = "genotype",
color = "genotype") +
guides(color = "none") +
guides(fill = guide_legend(nrow = 1, ncol = 2)) + # set fill legend to 1 row 2 columns.
theme_minimal() +
theme(legend.position = c(0.8, 0.15),
axis.line = element_line(size = 1.2),
text = element_text(size = 12, color = "black", face = "bold"),
axis.text = element_text(size = 12, color = "black", face = "bold")
)

We can also pull out the summary statistics. We’ll need to group by
genotype and age.f
rice_growth %>%
group_by(genotype, age.f) %>%
summarise(mean = mean(Height_mm),
var = var(Height_mm),
sd = sd(Height_mm),
n = n())
The variances seem to increase as the means increase, but I don’t
think it’s too bad (not orders of magnitude different). If you are
interested, you can try a log transformation and compare results. I
think the conclusions should practically be the same.
Stats
We have our model, now let’s check the assumptions of ANOVA
first.
Normality? It turns out the plot(model, which = 2)
command wouldn’t work on mixed effect models. We will use
qqnorm(resid(model)) instead. The resid()
function pull out all the residues in a model.
qqnorm(resid(model_rice))

Pretty normally distributed.
Equal variance across groups?
plot(model_rice)

It turns out when you call plot() on a mixed effect
model, it gives you the residue vs. mean plot. The residues seem to be
pretty evenly spread across the range of mean. The variances are more or
less even across groups, although there is a slightly larger spread at
the high end of the data.
So now we are all clear to do ANOVA.
ANOVA
anova(model_rice)
Type III Analysis of Variance Table with Satterthwaite's method
Sum Sq Mean Sq NumDF DenDF F value Pr(>F)
age.f 16398687 3279737 5 230.000 4578.6270 < 2.2e-16 ***
genotype 16523 16523 1 41.323 23.0673 2.078e-05 ***
age.f:genotype 18386 3677 5 230.000 5.1336 0.0001747 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Not surprisingly, age.f explain the most variation in the data (F =
4578)! Genotype also explains a significant amount of variation in the
dataset (F = 23 >> 1). The interaction between the treatments are
also significant (F = 5 > 1).
Tukey test
Let’s really not a question of whether or not the height is different
across age, because we know plants grow taller over time. The real
question is whether or not WT is taller or shorter than the mutant
across age.
So the emmeans layout should be
~ genotype | age.f
estimate_rice <- emmeans(model_rice, pairwise ~ genotype | age.f)
estimate_rice$contrast
age.f = 3:
contrast estimate SE df t.ratio p.value
(48/48) - WT -21.0 10.8 119 -1.949 0.0536
age.f = 4:
contrast estimate SE df t.ratio p.value
(48/48) - WT -31.6 10.8 119 -2.929 0.0041
age.f = 5:
contrast estimate SE df t.ratio p.value
(48/48) - WT -68.6 10.8 119 -6.368 <0.0001
age.f = 6:
contrast estimate SE df t.ratio p.value
(48/48) - WT -51.2 10.8 119 -4.755 <0.0001
age.f = 7:
contrast estimate SE df t.ratio p.value
(48/48) - WT -31.5 10.8 119 -2.921 0.0042
age.f = 9:
contrast estimate SE df t.ratio p.value
(48/48) - WT -28.3 10.8 119 -2.629 0.0097
Degrees-of-freedom method: satterthwaite
You can also look at cld if you like.
cld(estimate_rice$emmeans, Letters = letters)
age.f = 3:
genotype emmean SE df lower.CL upper.CL .group
48/48 92 14.0 9.18 60.3 124 a
WT 113 13.3 7.49 81.9 144 a
age.f = 4:
genotype emmean SE df lower.CL upper.CL .group
48/48 200 14.0 9.18 167.9 231 a
WT 231 13.3 7.49 200.0 262 b
age.f = 5:
genotype emmean SE df lower.CL upper.CL .group
48/48 328 14.0 9.18 296.2 359 a
WT 396 13.3 7.49 365.3 428 b
age.f = 6:
genotype emmean SE df lower.CL upper.CL .group
48/48 498 14.0 9.18 466.0 529 a
WT 549 13.3 7.49 517.8 580 b
age.f = 7:
genotype emmean SE df lower.CL upper.CL .group
48/48 646 14.0 9.18 614.2 677 a
WT 677 13.3 7.49 646.2 708 b
age.f = 9:
genotype emmean SE df lower.CL upper.CL .group
48/48 779 14.0 9.18 747.7 811 a
WT 808 13.3 7.49 776.5 839 b
Degrees-of-freedom method: satterthwaite
Confidence level used: 0.95
significance level used: alpha = 0.05
NOTE: If two or more means share the same grouping symbol,
then we cannot show them to be different.
But we also did not show them to be the same.
What does this tell us? It tells us that in each time point (except
the first), WT plants are on average significantly taller than 48/48
plants.
(Note: The differences in heights at week 9 is 28.3 mm. In reality,
~30 mm (3cm) difference in height is practically nothing for rice
plants. Even though something is statistically significant, it does not
always mean something practically different.)
Exercise
Now you have learned how to deal with repeated measures in an
experiment, it’s time for you to practice.
We will use a mint growth experiment as an example. In this
experiment, the researchers looked at the effect of 6 treatments (A - F)
on mint growth. Each treatment has 3 pots. Each pot has 4 plants. The
treatment was applied to the pot, not the individual plants. The growth
of each plant in each pot was measured. (Data from UC Davis Plant
Sciences course PLS205, Winter 2017)
mint_data <- read_csv("https://raw.githubusercontent.com/johnshorter/TeachingData/refs/heads/main/Mint.csv")
head(mint_data)
tail(mint_data)
There is a problem with how the data were recorded. Maybe it’s not
obvious to you. In each treatment, the name of the Pot is all Pot_1,
Pot_2 and Pot_3. However, in the actual experiment, Pot_1 from Treatment
A is not the same Pot_1 for Treatment B, or CDEF. The same applies to
Pot_2 and Pot_3. Simply put, the pots in each treatment need to have
their own unique identifier. Let’s fix that first.
mint_data <- mint_data %>%
mutate(Pot.ID = paste(Pot, Trtmt))
head(mint_data)
mint_data %>%
group_by(Trtmt) %>%
summarise(mean = mean(Growth),
var = var(Growth),
sd = sd(Growth),
n = n())
Now each pot has their own unique ID. Pot is the EU that has multiple
measurements.
Visualization
Make the best plot you can to visualize the data.
What to put on x axis? What to color/fill with? Any faceting that you
want to use?
Make your plot here:
mint_data %>%
mutate(Plant = factor(Plant)) %>%
ggplot(aes(x = Trtmt, y = Growth)) +
geom_point(aes(fill = Plant),
position = position_jitter(0.1, seed = 666),
alpha = 0.8,
size = 3,
shape = 21,
color = "black") +
scale_fill_manual(values = wisteria[c(1,2,3, 7)]) +
scale_color_manual(values = wisteria[c(1,2,3, 7)]) +
#scale_x_continuous(breaks = c(3, 4, 5, 6, 7, 9)) +
labs(x = "Treatment",
y = "Growth",
fill = "Plant",
color = "Plant") +
guides(color = "none") +
#guides(fill = guide_legend(nrow = 1, ncol = 2)) + # set fill legend to 1 row 2 columns.
theme_minimal() +
theme(legend.position = "bottom",
axis.line = element_line(size = 1.2),
text = element_text(size = 12, color = "black", face = "bold"),
axis.text = element_text(size = 12, color = "black", face = "bold")
)

What is being
repeatedly measured in this experiment?
Can you tell which entity was repeatably measured?
Fill in the table and write down the model. What are the sources of
variation? What factors are they? (treatment? block? observational
units? experimental units?) How many levels in each?
What is the experimental unit for treatment? What is the
observational unit?
| Trmt |
treat |
6 |
| Pot.ID |
EU |
18 |
| Pot.ID.Plant |
OU |
72 |
Technically plant could be a blocking factor if there was something
systematic about it e.g. coming from a certain seed container or
whatever, but in this we know nothing, it’s just a number, and doesn’t
seem to affect the treatments from visualizing the data.
Set up the linear model.
Check assumptions of
ANOVA
model_mint <- lmer(Growth ~ Trtmt + (1|Pot.ID), data = mint_data) # random intercept for Pot.ID
qqnorm(resid(model_rice))

plot(model_mint)

Normality?
Equal variance?
Run ANOVA
How would you interpret the ANOVA table?
anova(model_mint)
Type III Analysis of Variance Table with Satterthwaite's method
Sum Sq Mean Sq NumDF DenDF F value Pr(>F)
Trtmt 77.942 15.588 5 12 16.689 4.881e-05 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
F value significant, means of treatment groups are different.
Tukey test
Pull out the cld output and interpret the results.
estimate_mint <- emmeans(model_mint, pairwise ~ Trtmt)
estimate_mint$contrast
contrast estimate SE df t.ratio p.value
Trtmt_A - Trtmt_B -0.458 0.599 12 -0.765 0.9685
Trtmt_A - Trtmt_C -1.542 0.599 12 -2.574 0.1776
Trtmt_A - Trtmt_D -3.667 0.599 12 -6.121 0.0006
Trtmt_A - Trtmt_E -2.792 0.599 12 -4.661 0.0056
Trtmt_A - Trtmt_F -4.250 0.599 12 -7.095 0.0001
Trtmt_B - Trtmt_C -1.083 0.599 12 -1.809 0.4954
Trtmt_B - Trtmt_D -3.208 0.599 12 -5.356 0.0018
Trtmt_B - Trtmt_E -2.333 0.599 12 -3.895 0.0202
Trtmt_B - Trtmt_F -3.792 0.599 12 -6.330 0.0004
Trtmt_C - Trtmt_D -2.125 0.599 12 -3.548 0.0364
Trtmt_C - Trtmt_E -1.250 0.599 12 -2.087 0.3542
Trtmt_C - Trtmt_F -2.708 0.599 12 -4.521 0.0071
Trtmt_D - Trtmt_E 0.875 0.599 12 1.461 0.6929
Trtmt_D - Trtmt_F -0.583 0.599 12 -0.974 0.9178
Trtmt_E - Trtmt_F -1.458 0.599 12 -2.435 0.2187
Degrees-of-freedom method: kenward-roger
P value adjustment: tukey method for comparing a family of 6 estimates
cld(estimate_mint, Letters = letters)
Trtmt emmean SE df lower.CL upper.CL .group
Trtmt_A 3.67 0.424 12 2.74 4.59 a
Trtmt_B 4.12 0.424 12 3.20 5.05 a
Trtmt_C 5.21 0.424 12 4.29 6.13 ab
Trtmt_E 6.46 0.424 12 5.54 7.38 bc
Trtmt_D 7.33 0.424 12 6.41 8.26 c
Trtmt_F 7.92 0.424 12 6.99 8.84 c
Degrees-of-freedom method: kenward-roger
Confidence level used: 0.95
P value adjustment: tukey method for comparing a family of 6 estimates
significance level used: alpha = 0.05
NOTE: If two or more means share the same grouping symbol,
then we cannot show them to be different.
But we also did not show them to be the same.
Treatment F has the highest estimate but is not significantly
different from E and D
What to submit to
Moodle (Pass/Fail)
For this lesson, complete the exercises in your shared
Exercise Pack (the file
Exercise_Pack_Template.Rmd). Then Knit to
HTML and upload the HTML file to the Moodle exercise
folder.
File name format:
Lastname_Firstname_L11.html
Satisfactory / Not
satisfactory (what I check)
Your submission is Satisfactory if:
- It knits (HTML opens and shows your work).
- You included outputs (plots/tables/model output)
that match the lesson.
- You answered the Self-check checklist (short,
honest, and complete).
- Your work is plausible (right method for the
lesson, correct variables, no obvious copy/paste without results).
If one or more of these are missing, it is Not
satisfactory (and you resubmit). ## Additional exercises
(complete these in your Exercise Pack)
Exercise 2 — Random
intercept model
Fit a mixed model with a random intercept for subject (or repeated
unit). Compare it to a model without the random effect.
avg_mint <- mint_data %>% split(mint_data$Pot.ID) %>% lapply(function(x){
avg.growth <- mean(x$Growth)
unique.vars <- x %>% dplyr::select(c(Trtmt, Pot.ID)) %>% unique()
unique.vars %<>% mutate(avg_growth = avg.growth)
return(unique.vars)
}) %>% bind_rows()
model_mint_avg <- lm(avg_growth ~ Trtmt, data = avg_mint)
plot(model_mint_avg)




anova(model_mint_avg)
Analysis of Variance Table
Response: avg_growth
Df Sum Sq Mean Sq F value Pr(>F)
Trtmt 5 44.911 8.9821 16.689 4.881e-05 ***
Residuals 12 6.458 0.5382
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
estimate_mint_avg <- emmeans(model_mint_avg, pairwise ~ Trtmt)
estimate_mint_avg$contrast
contrast estimate SE df t.ratio p.value
Trtmt_A - Trtmt_B -0.458 0.599 12 -0.765 0.9685
Trtmt_A - Trtmt_C -1.542 0.599 12 -2.574 0.1776
Trtmt_A - Trtmt_D -3.667 0.599 12 -6.121 0.0006
Trtmt_A - Trtmt_E -2.792 0.599 12 -4.661 0.0056
Trtmt_A - Trtmt_F -4.250 0.599 12 -7.095 0.0001
Trtmt_B - Trtmt_C -1.083 0.599 12 -1.809 0.4954
Trtmt_B - Trtmt_D -3.208 0.599 12 -5.356 0.0018
Trtmt_B - Trtmt_E -2.333 0.599 12 -3.895 0.0202
Trtmt_B - Trtmt_F -3.792 0.599 12 -6.330 0.0004
Trtmt_C - Trtmt_D -2.125 0.599 12 -3.548 0.0364
Trtmt_C - Trtmt_E -1.250 0.599 12 -2.087 0.3542
Trtmt_C - Trtmt_F -2.708 0.599 12 -4.521 0.0071
Trtmt_D - Trtmt_E 0.875 0.599 12 1.461 0.6929
Trtmt_D - Trtmt_F -0.583 0.599 12 -0.974 0.9178
Trtmt_E - Trtmt_F -1.458 0.599 12 -2.435 0.2187
P value adjustment: tukey method for comparing a family of 6 estimates
cld(estimate_mint_avg, Letters = letters)
Trtmt emmean SE df lower.CL upper.CL .group
Trtmt_A 3.67 0.424 12 2.74 4.59 a
Trtmt_B 4.12 0.424 12 3.20 5.05 a
Trtmt_C 5.21 0.424 12 4.29 6.13 ab
Trtmt_E 6.46 0.424 12 5.54 7.38 bc
Trtmt_D 7.33 0.424 12 6.41 8.26 c
Trtmt_F 7.92 0.424 12 6.99 8.84 c
Confidence level used: 0.95
P value adjustment: tukey method for comparing a family of 6 estimates
significance level used: alpha = 0.05
NOTE: If two or more means share the same grouping symbol,
then we cannot show them to be different.
But we also did not show them to be the same.
Interestingly we get the exact same results. It turns out that with a
balanced dataset the mixed model reduces to averaging by the repeated
measurement covariates.
Self-check: you show both models and a short
justification for the random effect.
Exercise 3 —
Trajectory plot
Make a plot showing repeated measurements over time (or condition)
per subject.
Self-check: each subject has multiple points;
patterns are visible.
Exercise 4 —
Assumptions and residuals
Check residual diagnostics for the mixed model and state one
limitation.
Self-check: at least one diagnostic plot + one
limitation statement.
Exercise 5 —
Mini-transfer
Apply a mixed model idea to a different dataset (built-in or from the
lesson) with a sensible random effect.
Self-check: you clearly identify what is the
repeated/clustered unit.
LS0tCnRpdGxlOiAiMTEgLSBSZXBlYXRlZCBtZWFzdXJlcyBhbmQgbWl4ZWQgZWZmZWN0IG1vZGVscyIKYXV0aG9yOiAiSm9obiBTaG9ydGVyIgpkYXRlOiAiMTkvRGVjLzIwMjYiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB5ZXMgIAogIGh0bWxfbm90ZWJvb2s6ICAgCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcyAgICAKICAgIHRvYzogeWVzICAKICAgIHRvY19mbG9hdDogeWVzCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkobWFncml0dHIpCmBgYAoKIyBJbnRyb2R1Y3Rpb24KCldlIGNvdmVyZWQgb25lLXdheSBBTk9WQSwgcmFuZG9taXplZCBibG9jayBkZXNpZ24sIGFuZCBtdWx0aWZhY3RvcmlhbCBkZXNpZ24uCkFzIHlvdSBtYXkgaGF2ZSBhbHJlYWR5IGZpZ3VyZWQsIHdlIHN0YXJ0ZWQgd2l0aCBzaW1wbGUgZXhwZXJpbWVudGFsIGRlc2lnbnMsCmFuZCBncmFkdWFsbHkgbW92ZSB0b3dhcmRzIG1vcmUgY29tcGxleCBleHBlcmltZW50YWwgZGVzaWducy4KClRoaXMgdGltZSwgd2Ugd2lsbCBjb3ZlciBleHBlcmltZW50YWwgZGVzaWducyBpbnZvbHZpbmcgcmVwZWF0ZWQgbWVhc3VyZXMuIFdlIHdpbGwgY292ZXIKCjEuICBXaHkgaXMgcmVwZWF0ZWQgbWVhc3VyZSBhIHByb2JsZW0gZm9yIEFOT1ZBPwoyLiAgV2hhdCBpcyBhIHJhbmRvbSBlZmZlY3Q/CjMuICBIb3cgdG8gc2V0IHVwIGEgbWl4ZWQgZWZmZWN0IG1vZGVsPwo0LiAgSG93IHRvIGFuYWx5emUgYSBtaXhlZCBlZmZlY3QgbW9kZWw/CgojIExvYWQgcGFja2FnZXMKCmBgYHtyfQpsaWJyYXJ5KGxtZTQpCmxpYnJhcnkobG1lclRlc3QpICAgI3R3byBuZXcgcGFja2FnZXMKCgpsaWJyYXJ5KGVtbWVhbnMpICAKbGlicmFyeShtdWx0Y29tcCkKbGlicmFyeShtdWx0Y29tcFZpZXcpCmxpYnJhcnkoZ2dwbG90MikgCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocmVhZHIpCmxpYnJhcnkocmVhZHhsKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeSh2aXJpZGlzKQpgYGAKCiMgV2h5IGlzIHJlcGVhdGVkIG1lYXN1cmUgYSBwcm9ibGVtIGZvciBBTk9WQQoKUmVwZWF0ZWQgbWVhc3VyZXMgcmVmZXIgdG8gdGhlIGZhY3QgdGhhdCBpbiBzb21lIGV4cGVyaW1lbnRzLCB0aGUgc2FtZSBlbnRpdHkgaXMgbWVhc3VyZWQgbXVsdGlwbGUgdGltZXMuCkhvdyBjb3VsZCB0aGF0IGJlPwoKTGV0J3MgaW1hZ2luZSBhbiBleHBlcmltZW50IGxpa2UgdGhpczoKClNheSBJIGFtIHRyYWNraW5nIHRoZSBoZWlnaHRzIG9mIHNvbWUgcmljZSBwbGFudHMgb3ZlciB0aW1lLgpFdmVyeSB3ZWVrLCBJIGdvIHRvIG1lYXN1cmUgdGhlIGhlaWdodCBvZiB0aG9zZSBwbGFudHMuCgpBbmQgKlRIQVQqIGlzIGEga2luZCBvZiByZXBlYXRlZCBtZWFzdXJlLiBUaGUgc2FtZSBwbGFudHMgYXJlIG1lYXN1cmVkIG11bHRpcGxlIHRpbWVzIHRocm91Z2hvdXQgdGhlIGV4cGVyaW1lbnQuCldoZW5ldmVyIHRoZSBzYW1lIGVudGl0eSBpcyBtZWFzdXJlZCBtdWx0aXBsZSB0aW1lcyAoZWl0aGVyIGFjcm9zcyB0aW1lIG9yIHNwYWNlKSwKaXQgaXMgYSByZXBlYXRlZCBtZWFzdXJlcyBleHBlcmltZW50LgoKTGV0J3MgZ28gb3ZlciBhbm90aGVyIGV4YW1wbGUuClNheSBJIGFtIGludGVyZXN0ZWQgaW4gdGhlIG51bWJlciBvZiBzZWVkcyBwZXIgcGxhbnQgYWNyb3NzIHR3byBnZW5vdHlwZXMgb2YgcmljZS4KVGhlcmUgYXJlIHRocmVlIHBvdHMgcGVyIGdlbm90eXBlLCBhbmQgdGhyZWUgcGxhbnRzIHBlciBwb3QuIChBbGwgdGhyZWUgcGxhbnRzIGluIGEgcG90IGFyZSB0aGUgc2FtZSBnZW5vdHlwZS4pClRoZW4gSSBjb3VudCB0aGUgbnVtYmVyIG9mIHNlZWRzIGluIGVhY2ggcGxhbnQuXApBbmQgKlRIQVQqIGlzIGEgcmVwZWF0ZWQgbWVhc3VyZS4gVGhlIHBvdHMgYXJlIGJlaW5nIHJlcGVhdGVkbHkgbWVhc3VyZWQgZm9yIHRoZSBwbGFudHMgaW4gdGhlbS4KQW5kIHRoZSBwb3RzIGNhbm5vdCBiZSB1c2VkIGFzIGEgYmxvY2tpbmcgZmFjdG9yLCBiZWNhdXNlIHRoZXJlIGlzIG9ubHkgb25lIGdlbm90eXBlIHBlciBwb3QuCgpCdXQgd2h5IGlzIHRoYXQgYSBwcm9ibGVtPwpSZW1lbWJlciwgdGhlIGFzc3VtcHRpb24gb2YgQU5PVkEgaXMgdGhhdCBlYWNoIG9ic2VydmF0aW9uIGlzIGluZGVwZW5kZW50IG9mIHRoZSBvdGhlci4KQW5kIHJlcGVhdGVkIG1lYXN1cmVzIGlzIGEgdmlvbGF0aW9uIG9mIHRoYXQgYXNzdW1wdGlvbi4KV2hlbiBtdWx0aXBsZSBtZWFzdXJlbWVudHMgb2YgdGhlIHNhbWUgZW50aXR5IHdlcmUgdGFrZW4sCnRob3NlIG1lYXN1cmVtZW50cyB3aWxsIE5PVCBiZSBpbmRlcGVuZGVudCBvZiBlYWNoIG90aGVyLApiZWNhdXNlIHRoZXkgYXJlIGFsbCBhZmZlY3RlZCBieSB0aGUgc2FtZSBlbnRpdHkuCgpSZXBlYXRlZCBtZWFzdXJlcyBhbHdheXMgcmVkdWNlIHRoZSBudW1iZXIgb2YgaW5kZXBlbmRlbnQgb2JzZXJ2YXRpb25zIHlvdSBoYXZlLAphbmQgb25lIG11c3QgY29ycmVjdCBmb3IgcmVwZWF0ZWQgbWVhc3VyZXMuCgojIFdvcmtpbmcgd2l0aCByZXBlYXRlZCBtZWFzdXJlcyAtIHVzaW5nIHJhbmRvbSBlZmZlY3RzCgpUbyBjb3JyZWN0IGZvciByZXBlYXRlZCBtZWFzdXJlcywgd2UgbmVlZCB0byBkZWNsYXJlIHRoZSBlbnRpdGllcyB0aGF0IGFyZSByZXBlYXRlZGx5IG1lYXN1cmVkIGFzICJyYW5kb20gZWZmZWN0cyIuCgpUaGlzIGlzIGEgdmVyeSBhYnN0cmFjdCBjb25jZXB0LiBTbyB0aGUgYmVzdCB3YXkgdG8gZXhwbGFpbiBpcyB0byB1c2UgYW4gZXhhbXBsZS4KCldlIGFyZSBjb21wYXJpbmcgdGhlIGhlaWdodCBvZiB0d28gcmljZSBnZW5vdHlwZXMsIFdUIGFuZCBtdXRhbnQsIHRocm91Z2ggdGltZS4KRXZlcnkgd2VlayB3ZSBtZWFzdXJlIHRoZSBoZWlnaHRzIG9mIHRob3NlIHBsYW50cy4KKERhdGEgZnJvbSBTdW5kYXJlc2FuIExhYiwgRGVwYXJ0bWVudCBPZiBQbGFudCBCaW9sb2d5LCBVQyBEYXZpcykKCmBgYHtyfQpyaWNlX2dyb3d0aCA8LSByZWFkX2NzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2pvaG5zaG9ydGVyL1RlYWNoaW5nRGF0YS9yZWZzL2hlYWRzL21haW4vcmljZV9ncm93dGhfZGF0YS5jc3YiKQpoZWFkKHJpY2VfZ3Jvd3RoKQpgYGAKCkluIHRoaXMgZXhwZXJpbWVudCwgZWFjaCBwb3Qgd2FzIHJhbmRvbWx5IGFzc2lnbmVkIGEgZ2Vub3R5cGUsIGVpdGhlciBXVCBvciBtdXRhbnQuIFRoZSBtdXRhbnQgaXMgY2FsbGVkICI0OC80OCIuClRoZXJlIHdhcyBvbmUgcGxhbnQgcGVyIHBvdC4KVGhlIHRvdGFsIG9mIDQ4IHBvdHMgd2VyZSByYW5kb21seSBwbGFjZWQgaW50byA2IGZsYXRzLCBhbmQgOCBwb3RzIHBlciBmbGF0LgpTbyB0aGUgZmxhdCB3YXMgYSBibG9ja2luZyBmYWN0b3IuCldlIG1lYXN1cmUgdGhlIGhlaWdodCBldmVyeSB3ZWVrLCBzdGFydGluZyBmcm9tIHdlZWsgMyB0byB3ZWVrIDksIChidXQgbm90IHdlZWsgOCksIHNvIHRvdGFsIG9mIDYgdGltZSBwb2ludHMuCgpCZWZvcmUgd2UgdGFsayBhYm91dCByYW5kb20gZWZmZWN0cywgd2UgbmVlZCB0byB0YWxrIGFib3V0IGZpeGVkIGVmZmVjdHMuClNpbXBseSBwdXQsIHRoZSBmaXhlZCBlZmZlY3RzIGFyZSB5b3VyIHRyZWF0bWVudHMuCkluIHRoaXMgZXhhbXBsZSwgV2UgaGF2ZSB0d28gZml4ZWQgZWZmZWN0czogZ2Vub3R5cGUgYW5kIGFnZS4KCkxldCdzIGxvb2sgYXQgYWxsIHRoZSBmYWN0b3JzIGluIHRoaXMgZXhwZXJpbWVudAoKfCBzb3VyY2VzIHwgZmFjdG9yIHwgbGV2ZWxzIHwKfDotLS0tLS0tOnw6LS0tLS0tOnw6LS0tLS0tOnwKfCAgdGltZSAgIHwgdHJlYXQgIHwgICA2ICAgIHwKfCAgZ2Vub3QgIHwgdHJlYXQgIHwgICAyICAgIHwKfCAgZmxhdCAgIHwgYmxvY2sgIHwgICA2ICAgIHwKfCAgIHBvdCAgIHwgICpFVSogIHwgICA0OCAgIHwKCkJlY2F1c2UgdGhlcmUgYXJlIHR3byBpbmRlcGVuZGVudCB2YXJpYWJsZXMgKHRpbWUgYW5kIGdlbm90eXBlKSBhbmQgb25lIGJsb2NraW5nIGZhY3RvciwKdGhpcyBleHBlcmltZW50IHdpbGwgYmUgY2FsbGVkIGEgcmFuZG9taXplZCBibG9jayBtdWx0aWZhY3RvcmlhbCBkZXNpZ24uCgoqTm90ZSogSW4gdGhpcyBleGFtcGxlLCBwbGFudCBvciBwb3QgaXMgdGhlIGV4cGVyaW1lbnRhbCB1bml0IGZvciBnZW5vdHlwZSwKYmVjYXVzZSB0aGUgdHJlYXRtZW50IG9mIGdlbm90eXBlIHdhcyBhcHBsaWVkIHRvIGVhY2ggcG90LCBhbmQgdGhlcmUgaXMgb25seSBvbmUgcGxhbnQgaW4gZWFjaCBwb3QuCipOb3RlKiBQb3QgaXMgYWxzbyB0aGUgZW50aXR5IHRoYXQgaGFzIGJlZW4gcmVwZWF0ZWRseSBtZWFzdXJlZCB0aHJvdWdoIHdlZWtzLgoKWW91IG1pZ2h0IGFzaywgdGhlbiB3aGVyZSBpcyB0aGUgb2JzZXJ2YXRpb25hbCB1bml0PwpUaGUgT1UgaXMgYWN0dWFsIHRoZSBwbGFudCBhdCBlYWNoIHdlZWssIG9yIHRoZSBwbGFudDp3ZWVrIGNvbWJpbmF0aW9uLgoKQ29taW5nIGJhY2sgdG8gcmFuZG9tIGVmZmVjdHMuIFdoYXQgaXMgYSByYW5kb20gZWZmZWN0PwoKMS4gIEEgcmFuZG9tIGVmZmVjdCAqQ0FOTk9UKiBiZSBhIHRyZWF0bWVudCAoYmVjYXVzZSB0aGV5IGFyZSBmaXhlZCBlZmZlY3RzKTsKMi4gIEFuIEVVIHRoYXQgaXMgbm90IGFuIE9VIG11c3QgYmUgZGVjbGFyZWQgYXMgYSByYW5kb20gZWZmZWN0OwozLiAgQW4gZW50aXR5IHRoYXQgaXMgcmVwZWF0ZWRseSBtZWFzdXJlZCBtdXN0IGJlIGRlY2xhcmVkIGFzIGEgcmFuZG9tIGVmZmVjdDsKNC4gIEJsb2NraW5nIGZhY3RvcnMgY2FuIGJlIGRlY2xhcmVkIGFzIHJhbmRvbSBlZmZlY3RzLCBidXQgdGhleSBkb24ndCBoYXZlIHRvLgoKU28gaW4gdGhpcyBleGFtcGxlLCB3aGF0IG5lZWRzIHRvIGJlIGRlY2xhcmVkIGFzIGEgcmFuZG9tIGVmZmVjdD8KVGhlIHBvdCBuZWVkcyB0byBiZSBkZWNsYXJlZCBhcyBhIHJhbmRvbSBlZmZlY3QsCnNpbmNlIGl0IGlzIGJvdGggdGhlIEVVIGZvciBnZW5vdHlwZSBhbmQgdGhlIGVudGl0eSBvZiByZXBlYXRlZCBtZWFzdXJlcy4KCiMgU2V0dGluZyB1cCBhIG1peGVkIGVmZmVjdCBtb2RlbAoKQSBtaXhlZCBlZmZlY3QgbW9kZWwgcmVmZXJzIHRvIGEgbW9kZWwgdGhhdCBjb250YWlucyBib3RoIGZpeGVkIGVmZmVjdHMgYW5kIHJhbmRvbSBlZmZlY3RzLgpBIG1peGVkIGVmZmVjdCBtb2RlbCBpcyBhcHByb3ByaWF0ZSBmb3IgdGhpcyBleHBlcmltZW50LApiZWNhdXNlIHdlIGhhdmUgdHdvIGZpeGVkIGVmZmVjdHMgKHRpbWUgYW5kIGdlbm90eXBlKSBhbmQgb25lIHJhbmRvbSBlZmZlY3QgKHBvdCkuCiMjIyMgbm90ZSwgcG90IGlzIHRoZSBjb3ZhcmlhdGUgd2l0aGluIHdoaWNoIHdlIGhhdmUgcmVwZWF0ZWQgbWVhc3VyZXMKCkhvdyBkbyBJIHNldCB1cCB0aGUgbW9kZWw/ClRvIHNldCB1cCB0aGUgbWl4ZWQgZWZmZWN0IG1vZGVsLCB3ZSB3aWxsIG5lZWQgYSBuZXcgZnVuY3Rpb24uCkluc3RlYWQgb2YgYGxtKClgLCB3ZSB3aWxsIHVzZSBgbG1lcigpYC4gVGhpcyB3aWxsIGJlIHRoZSBjb21tYW5kIGZvciBtaXhlZCBlZmZlY3QgbGluZWFyIG1vZGVsLgoKVG8gc3BlY2lmeSBhIHJhbmRvbSBlZmZlY3QsIHdlJ2xsIHVzZSB0aGUgYCgxfHJhbmRvbV9lZmZlY3QpYCBzeW50YXguCkluIHRoaXMgZXhhbXBsZSwgaXQgd2lsbCBiZSBgKDF8cG90KWAKCkluIHRoZSBtb2RlbCwgeW91IHdpbGwgcHV0IGluIHlvdXIgZml4ZWQgZWZmZWN0IGFuZCBpbnRlcmFjdGlvbnMgZmlyc3QsCnRoZW4geW91IHB1dCBpbiBibG9ja2luZyBmYWN0b3JzLAp0aGVuIHlvdSBwdXQgaW4gcmFuZG9tIGVmZmVjdHMuClNvIHRoZSBtb2RlbCB3aWxsIGJlIGBsbWVyKGhlaWdodCB+IHRpbWUgKyBnZW5vdHlwZSArIHRpbWU6Z2Vub3R5cGUgKyBmbGF0ICsgKDF8cG90KSlgCllvdSBjYW4gYWxzbyBkbyBgdGltZSpnZW5vdHlwZSArIGZsYXQgKyAoMXxwb3QpLmAgVGhhdCBnaXZlcyB5b3UgdGhlIHNhbWUgdGhpbmcuCgpEbyBub3QgaW5jbHVkZSB0aGUgaW50ZXJhY3Rpb25zIHdpdGggYmxvY2tpbmcgZmFjdG9ycyAoZmxhdCkuClRoZSBibG9ja2luZyBmYWN0b3Igb25seSBleGlzdHMgdG8gY29udHJvbCBmb3IgdW5pbnRlbmRlZCB2YXJpYXRpb25zLgpBbmQgd2UgYXJlIG5vdCBpbnRlcmVzdGVkIGluIHRoZSBmbGF0OnRpbWUgb3IgZmxhdDpnZW5vdHlwZSBlZmZlY3RzLgoKWW91IG1pZ2h0IGFzayBjYW4gSSBkbyBgaGVpZ2h0IH4gZ2Vub3R5cGUgKiB0aW1lICsgZmxhdCArICgxfHBsYW50KWA/IEluIGFuIGV4cGVyaW1lbnQgbGlrZSB0aGlzLFwKeW91IHNob3VsZCBwdXQgdGhlIG5vbi1tYW5pcHVsYXRpdmUgZmFjdG9yICh0aW1lKSBmaXJzdCxcCnRoZW4geW91IHB1dCB0aGUgbWFuaXB1bGF0aXZlIGZhY3RvciAoZ2Vub3R5cGUpIHNlY29uZC4KClRoZSByZWFzb24gaXMgdGhhdCBpbiBhIG1peGVkIGVmZmVjdCBtb2RlbCwgdGhlIGZpcnN0IGZhY3RvciBpbiB0aGUgbW9kZWwgd2lsbCBhY2NvdW50IGZvciB2YXJpYXRpb24gZmlyc3Q7CnRoZW4gdGhlIHJlc3Qgb2YgdGhlIHZhcmlhdGlvbiB3aWxsIGJlIHBhc3NlZCBvbiB0byB0aGUgc2Vjb25kIGZhY3RvciBpbiB0aGUgbW9kZWwsCmFuZCBzbyBvbi4KCkJ5IGNvbW1vbiBzZW5zZSwgd2Uga25vdyBwbGFudHMgZ3JvdyB0YWxsZXIgb3ZlciB0aW1lLiBTbyB3ZSBleHBlY3QgdGhhdCB0aW1lIGV4cGxhaW5zIG1vcmUgdmFyaWF0aW9uIHRoYW4gZ2Vub3R5cGUuClNvIHdlIHdpbGwgcHV0IHRpbWUgZmlyc3QgaW4gdGhlIG1vZGVsLgoKWW91IGNhbiBhbHNvIGRlY2xhcmUgdGhlIGZsYXQgYXMgYSByYW5kb20gZWZmZWN0IGJ5IHVzaW5nIGAoMXxmbGF0KWAuCkVpdGhlciB3YXkgaXMgY29ycmVjdCwgYnV0IHNldHRpbmcgdGhlIGZsYXQgYXMgYSByYW5kb20gZWZmZWN0IGlzIG1vcmUgY29uc2VydmF0aXZlLAptZWFuaW5nIHlvdSdsbCBuZWVkIGEgbGFyZ2VyIGRpZmZlcmVuY2UgaW4gbWVhbiB0byBkZXRlY3QgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlCgpMYXN0IHRoaW5nOiBiZWZvcmUgeW91IHNldCB1cCB0aGUgbW9kZWwsIGlzIHRoZXJlIGFueSBudW1lcmljIHZhcmlhYmxlcyB0aGF0IHlvdSBuZWVkIHRvIGNoYW5nZSB0byBmYWN0b3JzPwoKYGBge3J9CnJpY2VfZ3Jvd3RoIDwtIHJpY2VfZ3Jvd3RoICU+JSAKICBtdXRhdGUoYWdlLmYgPSBmYWN0b3IoYWdlX3dlZWtzKSkgJT4lIAogIG11dGF0ZShmbGF0LmYgPSBmYWN0b3IoZmxhdCkpIApgYGAKCmBgYHtyfQptb2RlbF9yaWNlIDwtIGxtZXIoSGVpZ2h0X21tIH4gYWdlLmYgKiBnZW5vdHlwZSArICgxfGZsYXQuZikgKyAoMXxwb3QpLCBkYXRhID0gcmljZV9ncm93dGgpCmBgYAoKIyBEYXRhIHZpc3VhbGl6YXRpb24KCkJlZm9yZSB3ZSBkbyBhbnkgYW5hbHlzaXMsIGxldCdzIHBsb3QgdGhlIGRhdGEgYW5kIGxvb2sgYXQgaXQgZmlyc3QuClBsb3QgYWdlLmYgb24geCBheGlzLCBhbmQgSGVpZ2h0X21tIG9uIHkgYXhpcy4gQ29sb3IgYnkgZ2Vub3R5cGUuCgpNYWtlIHRoZSBiZXN0IHBsb3QgeW91IGNhbiBoZXJlOgoKYGBge3J9Cndpc3RlcmlhIDwtIGMoImdyZXk2NSIsICJidXJseXdvb2QzIiwgImtoYWtpMiIsICJwbHVtMSIsICJsaWdodGN5YW4yIiwgImNvcm5mbG93ZXJibHVlIiwgInNsYXRlYmx1ZTMiKQoKcmljZV9ncm93dGggJT4lIAogIGdncGxvdChhZXMoeCA9IGFnZV93ZWVrcywgeSA9IEhlaWdodF9tbSkpICsKICBzdGF0X3N1bW1hcnkoZ2VvbSA9ICJsaW5lIiwgIAogICAgICAgICAgICAgICBmdW4gPSBtZWFuLCAgCiAgICAgICAgICAgICAgIGFlcyhncm91cCA9IGdlbm90eXBlLCBjb2xvciA9IGdlbm90eXBlKSwgIAogICAgICAgICAgICAgICBzaXplID0gMS4yKSArIAogIHN0YXRfc3VtbWFyeShnZW9tID0gInJpYmJvbiIsICAgCiAgICAgICAgICAgICAgIGZ1bi5kYXRhID0gbWVhbl9zZSwgCiAgICAgICAgICAgICAgIGFlcyhncm91cCA9IGdlbm90eXBlLAogICAgICAgICAgICAgICAgICAgZmlsbCA9IGdlbm90eXBlKSwgCiAgICAgICAgICAgICAgIGFscGhhID0gMC41KSArICAgCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGdlbm90eXBlKSwgCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcigwLjEsIHNlZWQgPSA2NjYpLCAgICAKICAgICAgICAgICAgIGFscGhhID0gMC44LCAgICAgICAgICAgICAKICAgICAgICAgICAgIHNpemUgPSAzLAogICAgICAgICAgICAgc2hhcGUgPSAyMSwgCiAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpICsgICAgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gd2lzdGVyaWFbYygxLCA3KV0pICsgIAogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSB3aXN0ZXJpYVtjKDEsIDcpXSkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygzLCA0LCA1LCA2LCA3LCA5KSkgKyAgCiAgbGFicyh4ID0gIkFnZSAod2Vla3MpIiwgICAgICAgICAgICAgIAogICAgICAgeSA9ICJIZWlnaHQgbW0iLAogICAgICAgZmlsbCA9ICJnZW5vdHlwZSIsCiAgICAgICBjb2xvciA9ICJnZW5vdHlwZSIpICsKICBndWlkZXMoY29sb3IgPSAibm9uZSIpICsKICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChucm93ID0gMSwgbmNvbCA9IDIpKSArICMgc2V0IGZpbGwgbGVnZW5kIHRvIDEgcm93IDIgY29sdW1ucy4gCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDAuOCwgMC4xNSksCiAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKHNpemUgPSAxLjIpLCAKICAgICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgY29sb3IgPSAiYmxhY2siLCBmYWNlID0gImJvbGQiKSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBjb2xvciA9ICJibGFjayIsIGZhY2UgPSAiYm9sZCIpCiAgICAgICAgKQoKYGBgCgpXZSBjYW4gYWxzbyBwdWxsIG91dCB0aGUgc3VtbWFyeSBzdGF0aXN0aWNzLgpXZSdsbCBuZWVkIHRvIGdyb3VwIGJ5IGdlbm90eXBlIGFuZCBhZ2UuZgoKYGBge3J9CnJpY2VfZ3Jvd3RoICU+JSAKICBncm91cF9ieShnZW5vdHlwZSwgYWdlLmYpICU+JSAKICBzdW1tYXJpc2UobWVhbiA9IG1lYW4oSGVpZ2h0X21tKSwKICAgICAgICAgICAgdmFyID0gdmFyKEhlaWdodF9tbSksCiAgICAgICAgICAgIHNkID0gc2QoSGVpZ2h0X21tKSwKICAgICAgICAgICAgbiA9IG4oKSkgCmBgYAoKVGhlIHZhcmlhbmNlcyBzZWVtIHRvIGluY3JlYXNlIGFzIHRoZSBtZWFucyBpbmNyZWFzZSwgYnV0IEkgZG9uJ3QgdGhpbmsgaXQncyB0b28gYmFkIChub3Qgb3JkZXJzIG9mIG1hZ25pdHVkZSBkaWZmZXJlbnQpLgpJZiB5b3UgYXJlIGludGVyZXN0ZWQsIHlvdSBjYW4gdHJ5IGEgbG9nIHRyYW5zZm9ybWF0aW9uIGFuZCBjb21wYXJlIHJlc3VsdHMuIApJIHRoaW5rIHRoZSBjb25jbHVzaW9ucyBzaG91bGQgcHJhY3RpY2FsbHkgYmUgdGhlIHNhbWUuCgojIFN0YXRzCgpXZSBoYXZlIG91ciBtb2RlbCwgbm93IGxldCdzIGNoZWNrIHRoZSBhc3N1bXB0aW9ucyBvZiBBTk9WQSBmaXJzdC4KCk5vcm1hbGl0eT8KSXQgdHVybnMgb3V0IHRoZSBgcGxvdChtb2RlbCwgd2hpY2ggPSAyKWAgY29tbWFuZCB3b3VsZG4ndCB3b3JrIG9uIG1peGVkIGVmZmVjdCBtb2RlbHMuCldlIHdpbGwgdXNlIGBxcW5vcm0ocmVzaWQobW9kZWwpKWAgaW5zdGVhZC4KVGhlIGByZXNpZCgpYCBmdW5jdGlvbiBwdWxsIG91dCBhbGwgdGhlIHJlc2lkdWVzIGluIGEgbW9kZWwuCgpgYGB7cn0KcXFub3JtKHJlc2lkKG1vZGVsX3JpY2UpKQpgYGAKClByZXR0eSBub3JtYWxseSBkaXN0cmlidXRlZC4KCkVxdWFsIHZhcmlhbmNlIGFjcm9zcyBncm91cHM/CgpgYGB7cn0KcGxvdChtb2RlbF9yaWNlKQpgYGAKCkl0IHR1cm5zIG91dCB3aGVuIHlvdSBjYWxsIGBwbG90KClgIG9uIGEgbWl4ZWQgZWZmZWN0IG1vZGVsLCBpdCBnaXZlcyB5b3UgdGhlIHJlc2lkdWUgdnMuIG1lYW4gcGxvdC4KVGhlIHJlc2lkdWVzIHNlZW0gdG8gYmUgcHJldHR5IGV2ZW5seSBzcHJlYWQgYWNyb3NzIHRoZSByYW5nZSBvZiBtZWFuLgpUaGUgdmFyaWFuY2VzIGFyZSBtb3JlIG9yIGxlc3MgZXZlbiBhY3Jvc3MgZ3JvdXBzLCBhbHRob3VnaCB0aGVyZSBpcyBhIHNsaWdodGx5IGxhcmdlciBzcHJlYWQgYXQgdGhlIGhpZ2ggZW5kIG9mIHRoZSBkYXRhLgoKU28gbm93IHdlIGFyZSBhbGwgY2xlYXIgdG8gZG8gQU5PVkEuCgojIyBBTk9WQQoKYGBge3J9CmFub3ZhKG1vZGVsX3JpY2UpCmBgYAoKTm90IHN1cnByaXNpbmdseSwgYWdlLmYgZXhwbGFpbiB0aGUgbW9zdCB2YXJpYXRpb24gaW4gdGhlIGRhdGEgKEYgPSA0NTc4KSEKR2Vub3R5cGUgYWxzbyBleHBsYWlucyBhIHNpZ25pZmljYW50IGFtb3VudCBvZiB2YXJpYXRpb24gaW4gdGhlIGRhdGFzZXQgKEYgPSAyMyA+PiAxKS4KVGhlIGludGVyYWN0aW9uIGJldHdlZW4gdGhlIHRyZWF0bWVudHMgYXJlIGFsc28gc2lnbmlmaWNhbnQgKEYgPSA1ID4gMSkuCgojIyBUdWtleSB0ZXN0CgpMZXQncyByZWFsbHkgbm90IGEgcXVlc3Rpb24gb2Ygd2hldGhlciBvciBub3QgdGhlIGhlaWdodCBpcyBkaWZmZXJlbnQgYWNyb3NzIGFnZSwKYmVjYXVzZSB3ZSBrbm93IHBsYW50cyBncm93IHRhbGxlciBvdmVyIHRpbWUuClRoZSByZWFsIHF1ZXN0aW9uIGlzIHdoZXRoZXIgb3Igbm90IFdUIGlzIHRhbGxlciBvciBzaG9ydGVyIHRoYW4gdGhlIG11dGFudCBhY3Jvc3MgYWdlLgoKU28gdGhlIGBlbW1lYW5zYCBsYXlvdXQgc2hvdWxkIGJlIGB+IGdlbm90eXBlIHwgYWdlLmZgCgpgYGB7cn0KZXN0aW1hdGVfcmljZSA8LSBlbW1lYW5zKG1vZGVsX3JpY2UsIHBhaXJ3aXNlIH4gZ2Vub3R5cGUgfCBhZ2UuZikKZXN0aW1hdGVfcmljZSRjb250cmFzdApgYGAKCllvdSBjYW4gYWxzbyBsb29rIGF0IGNsZCBpZiB5b3UgbGlrZS4KCmBgYHtyfQpjbGQoZXN0aW1hdGVfcmljZSRlbW1lYW5zLCBMZXR0ZXJzID0gbGV0dGVycykKYGBgCgpXaGF0IGRvZXMgdGhpcyB0ZWxsIHVzPwpJdCB0ZWxscyB1cyB0aGF0IGluIGVhY2ggdGltZSBwb2ludCAoZXhjZXB0IHRoZSBmaXJzdCksCldUIHBsYW50cyBhcmUgb24gYXZlcmFnZSBzaWduaWZpY2FudGx5IHRhbGxlciB0aGFuIDQ4LzQ4IHBsYW50cy4KCihOb3RlOiBUaGUgZGlmZmVyZW5jZXMgaW4gaGVpZ2h0cyBhdCB3ZWVrIDkgaXMgMjguMyBtbS4KSW4gcmVhbGl0eSwgfjMwIG1tICgzY20pIGRpZmZlcmVuY2UgaW4gaGVpZ2h0IGlzIHByYWN0aWNhbGx5IG5vdGhpbmcgZm9yIHJpY2UgcGxhbnRzLgpFdmVuIHRob3VnaCBzb21ldGhpbmcgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCwgaXQgZG9lcyBub3QgYWx3YXlzIG1lYW4gc29tZXRoaW5nIHByYWN0aWNhbGx5IGRpZmZlcmVudC4pCgojIEV4ZXJjaXNlCgpOb3cgeW91IGhhdmUgbGVhcm5lZCBob3cgdG8gZGVhbCB3aXRoIHJlcGVhdGVkIG1lYXN1cmVzIGluIGFuIGV4cGVyaW1lbnQsCml0J3MgdGltZSBmb3IgeW91IHRvIHByYWN0aWNlLgoKV2Ugd2lsbCB1c2UgYSBtaW50IGdyb3d0aCBleHBlcmltZW50IGFzIGFuIGV4YW1wbGUuCkluIHRoaXMgZXhwZXJpbWVudCwgdGhlIHJlc2VhcmNoZXJzIGxvb2tlZCBhdCB0aGUgZWZmZWN0IG9mIDYgdHJlYXRtZW50cyAoQSAtIEYpIG9uIG1pbnQgZ3Jvd3RoLgpFYWNoIHRyZWF0bWVudCBoYXMgMyBwb3RzLgpFYWNoIHBvdCBoYXMgNCBwbGFudHMuIFRoZSB0cmVhdG1lbnQgd2FzIGFwcGxpZWQgdG8gdGhlIHBvdCwgbm90IHRoZSBpbmRpdmlkdWFsIHBsYW50cy4KVGhlIGdyb3d0aCBvZiBlYWNoIHBsYW50IGluIGVhY2ggcG90IHdhcyBtZWFzdXJlZC4KKERhdGEgZnJvbSBVQyBEYXZpcyBQbGFudCBTY2llbmNlcyBjb3Vyc2UgUExTMjA1LCBXaW50ZXIgMjAxNykKCmBgYHtyfQptaW50X2RhdGEgPC0gcmVhZF9jc3YoImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9qb2huc2hvcnRlci9UZWFjaGluZ0RhdGEvcmVmcy9oZWFkcy9tYWluL01pbnQuY3N2IikKaGVhZChtaW50X2RhdGEpCnRhaWwobWludF9kYXRhKQoKYGBgCgpUaGVyZSBpcyBhIHByb2JsZW0gd2l0aCBob3cgdGhlIGRhdGEgd2VyZSByZWNvcmRlZC4gTWF5YmUgaXQncyBub3Qgb2J2aW91cyB0byB5b3UuCkluIGVhY2ggdHJlYXRtZW50LCB0aGUgbmFtZSBvZiB0aGUgUG90IGlzIGFsbCBQb3RfMSwgUG90XzIgYW5kIFBvdF8zLgpIb3dldmVyLCBpbiB0aGUgYWN0dWFsIGV4cGVyaW1lbnQsIFBvdF8xIGZyb20gVHJlYXRtZW50IEEgaXMgbm90IHRoZSBzYW1lIFBvdF8xIGZvciBUcmVhdG1lbnQgQiwgb3IgQ0RFRi4KVGhlIHNhbWUgYXBwbGllcyB0byBQb3RfMiBhbmQgUG90XzMuClNpbXBseSBwdXQsIHRoZSBwb3RzIGluIGVhY2ggdHJlYXRtZW50IG5lZWQgdG8gaGF2ZSB0aGVpciBvd24gdW5pcXVlIGlkZW50aWZpZXIuCkxldCdzIGZpeCB0aGF0IGZpcnN0LgoKYGBge3J9Cm1pbnRfZGF0YSA8LSBtaW50X2RhdGEgJT4lIAogIG11dGF0ZShQb3QuSUQgPSBwYXN0ZShQb3QsIFRydG10KSkKCmhlYWQobWludF9kYXRhKQptaW50X2RhdGEgJT4lIAogIGdyb3VwX2J5KFRydG10KSAlPiUgCiAgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKEdyb3d0aCksCiAgICAgICAgICAgIHZhciA9IHZhcihHcm93dGgpLAogICAgICAgICAgICBzZCA9IHNkKEdyb3d0aCksCiAgICAgICAgICAgIG4gPSBuKCkpIApgYGAKCk5vdyBlYWNoIHBvdCBoYXMgdGhlaXIgb3duIHVuaXF1ZSBJRC4KUG90IGlzIHRoZSBFVSB0aGF0IGhhcyBtdWx0aXBsZSBtZWFzdXJlbWVudHMuCgojIyBWaXN1YWxpemF0aW9uCgpNYWtlIHRoZSBiZXN0IHBsb3QgeW91IGNhbiB0byB2aXN1YWxpemUgdGhlIGRhdGEuCgpXaGF0IHRvIHB1dCBvbiB4IGF4aXM/IFdoYXQgdG8gY29sb3IvZmlsbCB3aXRoPyBBbnkgZmFjZXRpbmcgdGhhdCB5b3Ugd2FudCB0byB1c2U/CgpNYWtlIHlvdXIgcGxvdCBoZXJlOgoKYGBge3J9Cm1pbnRfZGF0YSAlPiUgCiAgbXV0YXRlKFBsYW50ID0gZmFjdG9yKFBsYW50KSkgJT4lIAogIGdncGxvdChhZXMoeCA9IFRydG10LCB5ID0gR3Jvd3RoKSkgKwogIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBQbGFudCksIAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIoMC4xLCBzZWVkID0gNjY2KSwgICAgCiAgICAgICAgICAgICBhbHBoYSA9IDAuOCwgICAgICAgICAgICAgCiAgICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICAgIHNoYXBlID0gMjEsIAogICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSArICAgIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHdpc3RlcmlhW2MoMSwyLDMsIDcpXSkgKyAgCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHdpc3RlcmlhW2MoMSwyLDMsIDcpXSkgKyAKICAjc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoMywgNCwgNSwgNiwgNywgOSkpICsgIAogIGxhYnMoeCA9ICJUcmVhdG1lbnQiLCAgICAgICAgICAgICAgCiAgICAgICB5ID0gIkdyb3d0aCIsCiAgICAgICBmaWxsID0gIlBsYW50IiwKICAgICAgIGNvbG9yID0gIlBsYW50IikgKwogIGd1aWRlcyhjb2xvciA9ICJub25lIikgKwogICNndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChucm93ID0gMSwgbmNvbCA9IDIpKSArICMgc2V0IGZpbGwgbGVnZW5kIHRvIDEgcm93IDIgY29sdW1ucy4gCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoc2l6ZSA9IDEuMiksIAogICAgICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBjb2xvciA9ICJibGFjayIsIGZhY2UgPSAiYm9sZCIpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGNvbG9yID0gImJsYWNrIiwgZmFjZSA9ICJib2xkIikKICAgICAgICApCmBgYAoKIyMgV2hhdCBpcyBiZWluZyByZXBlYXRlZGx5IG1lYXN1cmVkIGluIHRoaXMgZXhwZXJpbWVudD8KCkNhbiB5b3UgdGVsbCB3aGljaCBlbnRpdHkgd2FzIHJlcGVhdGFibHkgbWVhc3VyZWQ/CgpGaWxsIGluIHRoZSB0YWJsZSBhbmQgd3JpdGUgZG93biB0aGUgbW9kZWwuCldoYXQgYXJlIHRoZSBzb3VyY2VzIG9mIHZhcmlhdGlvbj8KV2hhdCBmYWN0b3JzIGFyZSB0aGV5PyAodHJlYXRtZW50PyBibG9jaz8gb2JzZXJ2YXRpb25hbCB1bml0cz8gZXhwZXJpbWVudGFsIHVuaXRzPykKSG93IG1hbnkgbGV2ZWxzIGluIGVhY2g/CgoKV2hhdCBpcyB0aGUgZXhwZXJpbWVudGFsIHVuaXQgZm9yIHRyZWF0bWVudD8KV2hhdCBpcyB0aGUgb2JzZXJ2YXRpb25hbCB1bml0PwoKfCBzb3VyY2VzIHwgZmFjdG9yIHwgbGV2ZWxzIHwKfDotLS0tLS0tOnw6LS0tLS0tOnw6LS0tLS0tOnwKfCAgVHJtdCAgIHwgdHJlYXQgIHwgICA2ICAgIHwKfCBQb3QuSUQgIHwgICpFVSogIHwgICAxOCAgIHwKfCBQb3QuSUQuUGxhbnQgfCAqT1UqIHwgNzIgfAoKVGVjaG5pY2FsbHkgcGxhbnQgY291bGQgYmUgYSBibG9ja2luZyBmYWN0b3IgaWYgdGhlcmUgd2FzIHNvbWV0aGluZyBzeXN0ZW1hdGljIGFib3V0IGl0IGUuZy4gY29taW5nIGZyb20gYSBjZXJ0YWluIHNlZWQgY29udGFpbmVyIG9yIHdoYXRldmVyLCBidXQgaW4gdGhpcyB3ZSBrbm93IG5vdGhpbmcsIGl0J3MganVzdCBhIG51bWJlciwgYW5kIGRvZXNuJ3Qgc2VlbSB0byBhZmZlY3QgdGhlIHRyZWF0bWVudHMgZnJvbSB2aXN1YWxpemluZyB0aGUgZGF0YS4KClNldCB1cCB0aGUgbGluZWFyIG1vZGVsLgoKIyMgQ2hlY2sgYXNzdW1wdGlvbnMgb2YgQU5PVkEKCmBgYHtyfQptb2RlbF9taW50IDwtIGxtZXIoR3Jvd3RoIH4gVHJ0bXQgKyAoMXxQb3QuSUQpLCBkYXRhID0gbWludF9kYXRhKSAjIHJhbmRvbSBpbnRlcmNlcHQgZm9yIFBvdC5JRApxcW5vcm0ocmVzaWQobW9kZWxfcmljZSkpCnBsb3QobW9kZWxfbWludCkKYGBgCgpOb3JtYWxpdHk/CgpFcXVhbCB2YXJpYW5jZT8KCiMjIFJ1biBBTk9WQQoKSG93IHdvdWxkIHlvdSBpbnRlcnByZXQgdGhlIEFOT1ZBIHRhYmxlPwoKYGBge3J9CmFub3ZhKG1vZGVsX21pbnQpCmBgYApGIHZhbHVlIHNpZ25pZmljYW50LCBtZWFucyBvZiB0cmVhdG1lbnQgZ3JvdXBzIGFyZSBkaWZmZXJlbnQuCgojIyBUdWtleSB0ZXN0CgpQdWxsIG91dCB0aGUgY2xkIG91dHB1dCBhbmQgaW50ZXJwcmV0IHRoZSByZXN1bHRzLgoKYGBge3J9CmVzdGltYXRlX21pbnQgPC0gZW1tZWFucyhtb2RlbF9taW50LCBwYWlyd2lzZSB+IFRydG10KQplc3RpbWF0ZV9taW50JGNvbnRyYXN0CmBgYAoKYGBge3J9CmNsZChlc3RpbWF0ZV9taW50LCBMZXR0ZXJzID0gbGV0dGVycykKYGBgCgpUcmVhdG1lbnQgRiBoYXMgdGhlIGhpZ2hlc3QgZXN0aW1hdGUgYnV0IGlzIG5vdCBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIEUgYW5kIEQKCiMjIFdoYXQgdG8gc3VibWl0IHRvIE1vb2RsZSAoUGFzcy9GYWlsKQoKRm9yIHRoaXMgbGVzc29uLCBjb21wbGV0ZSB0aGUgZXhlcmNpc2VzICoqaW4geW91ciBzaGFyZWQgRXhlcmNpc2UgUGFjayoqICh0aGUgZmlsZSBgRXhlcmNpc2VfUGFja19UZW1wbGF0ZS5SbWRgKS4KVGhlbiAqKktuaXQgdG8gSFRNTCoqIGFuZCB1cGxvYWQgdGhlIEhUTUwgZmlsZSB0byB0aGUgTW9vZGxlIGV4ZXJjaXNlIGZvbGRlci4KCioqRmlsZSBuYW1lIGZvcm1hdDoqKiBgTGFzdG5hbWVfRmlyc3RuYW1lX0wxMS5odG1sYAoKIyMjIFNhdGlzZmFjdG9yeSAvIE5vdCBzYXRpc2ZhY3RvcnkgKHdoYXQgSSBjaGVjaykKCllvdXIgc3VibWlzc2lvbiBpcyAqKlNhdGlzZmFjdG9yeSoqIGlmOgoKLSBJdCAqKmtuaXRzKiogKEhUTUwgb3BlbnMgYW5kIHNob3dzIHlvdXIgd29yaykuCi0gWW91IGluY2x1ZGVkICoqb3V0cHV0cyoqIChwbG90cy90YWJsZXMvbW9kZWwgb3V0cHV0KSB0aGF0IG1hdGNoIHRoZSBsZXNzb24uCi0gWW91IGFuc3dlcmVkIHRoZSAqKlNlbGYtY2hlY2sgY2hlY2tsaXN0KiogKHNob3J0LCBob25lc3QsIGFuZCBjb21wbGV0ZSkuCi0gWW91ciB3b3JrIGlzICoqcGxhdXNpYmxlKiogKHJpZ2h0IG1ldGhvZCBmb3IgdGhlIGxlc3NvbiwgY29ycmVjdCB2YXJpYWJsZXMsIG5vIG9idmlvdXMgY29weS9wYXN0ZSB3aXRob3V0IHJlc3VsdHMpLgoKSWYgb25lIG9yIG1vcmUgb2YgdGhlc2UgYXJlIG1pc3NpbmcsIGl0IGlzICoqTm90IHNhdGlzZmFjdG9yeSoqIChhbmQgeW91IHJlc3VibWl0KS4KIyMgQWRkaXRpb25hbCBleGVyY2lzZXMgKGNvbXBsZXRlIHRoZXNlIGluIHlvdXIgRXhlcmNpc2UgUGFjaykKCiMjIyBFeGVyY2lzZSAyIOKAlCBSYW5kb20gaW50ZXJjZXB0IG1vZGVsCkZpdCBhIG1peGVkIG1vZGVsIHdpdGggYSByYW5kb20gaW50ZXJjZXB0IGZvciBzdWJqZWN0IChvciByZXBlYXRlZCB1bml0KS4KQ29tcGFyZSBpdCB0byBhIG1vZGVsIHdpdGhvdXQgdGhlIHJhbmRvbSBlZmZlY3QuCgpgYGB7cn0KYXZnX21pbnQgPC0gbWludF9kYXRhICU+JSBzcGxpdChtaW50X2RhdGEkUG90LklEKSAlPiUgbGFwcGx5KGZ1bmN0aW9uKHgpewogIGF2Zy5ncm93dGggPC0gbWVhbih4JEdyb3d0aCkKICB1bmlxdWUudmFycyA8LSB4ICU+JSBkcGx5cjo6c2VsZWN0KGMoVHJ0bXQsIFBvdC5JRCkpICU+JSB1bmlxdWUoKQogIHVuaXF1ZS52YXJzICU8PiUgbXV0YXRlKGF2Z19ncm93dGggPSBhdmcuZ3Jvd3RoKQogIHJldHVybih1bmlxdWUudmFycykKfSkgJT4lIGJpbmRfcm93cygpCgptb2RlbF9taW50X2F2ZyA8LSBsbShhdmdfZ3Jvd3RoIH4gVHJ0bXQsIGRhdGEgPSBhdmdfbWludCkKcGxvdChtb2RlbF9taW50X2F2ZykKYGBgCgoKYGBge3J9CmFub3ZhKG1vZGVsX21pbnRfYXZnKQpgYGAKCmBgYHtyfQplc3RpbWF0ZV9taW50X2F2ZyA8LSBlbW1lYW5zKG1vZGVsX21pbnRfYXZnLCBwYWlyd2lzZSB+IFRydG10KQplc3RpbWF0ZV9taW50X2F2ZyRjb250cmFzdApjbGQoZXN0aW1hdGVfbWludF9hdmcsIExldHRlcnMgPSBsZXR0ZXJzKQpgYGAKCkludGVyZXN0aW5nbHkgd2UgZ2V0IHRoZSBleGFjdCBzYW1lIHJlc3VsdHMuIEl0IHR1cm5zIG91dCB0aGF0IHdpdGggYSBiYWxhbmNlZCBkYXRhc2V0IHRoZSBtaXhlZCBtb2RlbCByZWR1Y2VzIHRvIGF2ZXJhZ2luZyBieSB0aGUgcmVwZWF0ZWQgbWVhc3VyZW1lbnQgY292YXJpYXRlcy4KCioqU2VsZi1jaGVjazoqKiB5b3Ugc2hvdyBib3RoIG1vZGVscyBhbmQgYSBzaG9ydCBqdXN0aWZpY2F0aW9uIGZvciB0aGUgcmFuZG9tIGVmZmVjdC4KCiMjIyBFeGVyY2lzZSAzIOKAlCBUcmFqZWN0b3J5IHBsb3QKTWFrZSBhIHBsb3Qgc2hvd2luZyByZXBlYXRlZCBtZWFzdXJlbWVudHMgb3ZlciB0aW1lIChvciBjb25kaXRpb24pIHBlciBzdWJqZWN0LgoKKipTZWxmLWNoZWNrOioqIGVhY2ggc3ViamVjdCBoYXMgbXVsdGlwbGUgcG9pbnRzOyBwYXR0ZXJucyBhcmUgdmlzaWJsZS4KCiMjIyBFeGVyY2lzZSA0IOKAlCBBc3N1bXB0aW9ucyBhbmQgcmVzaWR1YWxzCkNoZWNrIHJlc2lkdWFsIGRpYWdub3N0aWNzIGZvciB0aGUgbWl4ZWQgbW9kZWwgYW5kIHN0YXRlIG9uZSBsaW1pdGF0aW9uLgoKKipTZWxmLWNoZWNrOioqIGF0IGxlYXN0IG9uZSBkaWFnbm9zdGljIHBsb3QgKyBvbmUgbGltaXRhdGlvbiBzdGF0ZW1lbnQuCgojIyMgRXhlcmNpc2UgNSDigJQgTWluaS10cmFuc2ZlcgpBcHBseSBhIG1peGVkIG1vZGVsIGlkZWEgdG8gYSBkaWZmZXJlbnQgZGF0YXNldCAoYnVpbHQtaW4gb3IgZnJvbSB0aGUgbGVzc29uKSB3aXRoIGEgc2Vuc2libGUgcmFuZG9tIGVmZmVjdC4KCioqU2VsZi1jaGVjazoqKiB5b3UgY2xlYXJseSBpZGVudGlmeSB3aGF0IGlzIHRoZSByZXBlYXRlZC9jbHVzdGVyZWQgdW5pdC4K